﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using TerminationCall.Core;
using TerminationCall.Editor.Logic;
using System.Threading;
using System.IO;

namespace TerminationCall.Editor.GUI
{
    public partial class LevelForm : Form
    {
        const int ResolutionX = 480;
        const int ResolutionY = 272;

        private Renderer _renderer;

        private EditorTool _editorTool;
        private PaintToolSet _paintToolSet;

        private Bitmap _mainDrawBitmap;
        private Graphics _mainDrawGraphic;
        private Graphics _panelGraphic;

        private PaintTool _currentPaintTool;

        public EditorTool EditorTool {
            get {
                return _editorTool;
            }
        }

        public LevelForm(EditorTool editorTool, PaintToolSet paintToolSet)
        {
            InitializeComponent();

            _editorTool = editorTool;
            _paintToolSet = paintToolSet;

            _mainDrawBitmap = new Bitmap(ResolutionX, ResolutionY);
            _mainDrawGraphic = Graphics.FromImage(_mainDrawBitmap);
            _panelGraphic = pnlLevelGraphic.CreateGraphics();

            _renderer = new Renderer(_editorTool);

            LevelLoader levelLoader = new LevelLoader();
            EditorTool.Level = levelLoader.Load(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "test.lev"));

        }

        private void hsbLevel_Scroll(object sender, ScrollEventArgs e)
        {
            _editorTool.Offset = new Point(hsbLevel.Value, 0);
            RenderGraphics();
        }

        private void pnlLevelGraphic_MouseDown(object sender, MouseEventArgs e)
        {
            if (_currentPaintTool != null) {
                _currentPaintTool.CancelPainting();
                _currentPaintTool = null;
                RenderGraphics();
                return;
            }

            _currentPaintTool = MouseEventArgsHelper.GetPaintToolByMouseEventArgs(_paintToolSet, e);

            _currentPaintTool.StartPainting(new Point(e.X, e.Y));
            _currentPaintTool.Paint(new Point(e.X, e.Y));

            RenderGraphics();
        }

        private void pnlLevelGraphic_MouseUp(object sender, MouseEventArgs e)
        {
            if (_currentPaintTool == null) {
                return;
            }

            _currentPaintTool.StopPainting();
            _currentPaintTool = null;
        }

        private void pnlLevelGraphic_MouseMove(object sender, MouseEventArgs e) {

            PaintTool paintTool = MouseEventArgsHelper.GetPaintToolByMouseEventArgs(_paintToolSet, e);
            
            if (!paintTool.IsPainting) {
                RenderGraphics(new Point(e.X / TileConstants.TileSizeX * TileConstants.TileSizeX, e.Y / TileConstants.TileSizeY * TileConstants.TileSizeY));
                return;
            }
            
            paintTool.Paint(new Point(e.X, e.Y));

            RenderGraphics();
        }

        public void RenderGraphics(Point selection) {

            DateTime dtNow = DateTime.Now;
            TimeSpan dtDifference;

            _mainDrawGraphic.DrawImage(_renderer.RenderLevel(_editorTool.Offset), Point.Empty);

            _mainDrawGraphic.DrawImage(_renderer.RenderSelection(_editorTool.ChoosenTileSet, _editorTool.ChoosenTiles), selection);

            _panelGraphic.DrawImage(_mainDrawBitmap, Point.Empty);

            dtDifference = DateTime.Now - dtNow;

            if (dtDifference.TotalMilliseconds != 0) {
                lblRenderingTime.Text = "Rendering Time: " + dtDifference.TotalMilliseconds + " - Frames : " + (1000 / dtDifference.TotalMilliseconds).ToString();
            }
        }

        public void RenderGraphics()
        {
            DateTime dtNow = DateTime.Now;
            TimeSpan dtDifference;

            _mainDrawGraphic.DrawImage(_renderer.RenderLevel(_editorTool.Offset), Point.Empty);

            _panelGraphic.DrawImage(_mainDrawBitmap, Point.Empty);

            dtDifference = DateTime.Now - dtNow;

            if (dtDifference.TotalMilliseconds != 0)
            {
                lblRenderingTime.Text = "Rendering Time: " + dtDifference.TotalMilliseconds + " - Frames : " + (1000 / dtDifference.TotalMilliseconds).ToString();
            }
        }

        private void pnlLevelGraphic_Paint(object sender, PaintEventArgs e) {
            RenderGraphics();
        }

        private void LevelForm_KeyDown(object sender, KeyEventArgs e) {

            PaintTool paintTool = MouseEventArgsHelper.GetPaintToolByMouseEventArgs(_paintToolSet, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));

            if (e.Control) {

                switch (e.KeyCode) {

                    case Keys.Z:
                        paintTool.Undo();
                        RenderGraphics();
                        break;

                    case Keys.Y:
                        paintTool.Redo();
                        RenderGraphics();
                        break;
                }
            }
        }
    }
}
